/**
 * 
 */
package io.dora.remoting;

import io.dora.base.Protocol;
import io.dora.utils.ReflectionUtils;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 服务提供方Provider Server Socket实现
 * 
 * @author zhaohongbo
 *
 */
public class ScoketProviderServer extends AbstractProviderServer {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	private ServerSocket server;
	
	public ScoketProviderServer(Protocol protocol) {
		super(protocol);
	}

	@Override
	public void doServerStart() {
		try {
			server = new ServerSocket(protocol.getServicePort());
			logger.info("server startup on {}", server.getLocalPort());
			for(;;) {
				final Socket socket = server.accept();
				new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							logger.info("begin request handler...");
							ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
							// 获取方法名称
							String serviceKeyMethod = input.readUTF();
							String[] smArr = StringUtils.split(serviceKeyMethod, "?");
							Class<?>[] parameterType = (Class<?>[]) input.readObject();
							Object[] parameters = (Object[]) input.readObject();
							Object serviceObject = serviceMap.get(smArr[0]);
							
							if (serviceObject == null) {
								throw new IllegalArgumentException("can not locate service ");
							}
							
							Object resultObject = ReflectionUtils.invokeMethod(serviceObject, smArr[1], parameterType, parameters);
							ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
							output.writeObject(resultObject);
							
							input.close();
							output.close();
							socket.close();
							logger.info("end request handler...");
						} catch (Exception e) {
							logger.info("{}", e);
						}
					}
				}, "dazzle_service_provider_server").start();
			}
		} catch (Exception e) {
			logger.info("{}", e);
		}
	}

	@Override
	public void doServerStop() {
		if (server != null) {
			try {
				server.close();
			} catch (IOException e) {
				logger.info("{}", e);
			}
			server = null;
		}
	}
}
